package com.free.semantic.infrastruct.repository.impl;

import com.free.semantic.common.RelationItem;
import com.free.semantic.infrastruct.common.SemanticNetworkDO;
import com.free.semantic.infrastruct.mapper.SemanticNetworkMapper;
import com.free.semantic.infrastruct.repository.*;
import com.free.semantic.model.conceptmodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Repository
public class SemanticNetworkRepositoryImpl implements SemanticNetworkRepository {

    @Autowired
    private SemanticNetworkMapper semanticNetworkMapper;

    @Autowired
    private ConceptObjectRepository conceptObjectRepository;

    @Autowired
    private RelationItemRepository relationItemRepository;

    @Autowired
    private RelationDefineRepository relationDefineRepository;

    @Autowired
    private RelationDefineItemRepository relationDefineItemRepository;


    @Autowired
    private RelationImplRepository relationImplRepository;

    @Override
    public SemanticNetwork findById(Long id) {
        SemanticNetworkDO networkDO = semanticNetworkMapper.findById(id);
        if (networkDO == null) {
            return null;
        }
        return getCompleteSemanticNetwork(networkDO);
    }

    @Override
    public List<SemanticNetwork> findByUserId(Long userId) {
        List<SemanticNetworkDO> networkDOs = semanticNetworkMapper.findByUserId(userId);
        return networkDOs.stream()
                .map(this::getCompleteSemanticNetwork)
                .collect(Collectors.toList());
    }

    @Override
    public List<SemanticNetwork> findAll() {
        List<SemanticNetworkDO> networkDOs = semanticNetworkMapper.findAll();
        return networkDOs.stream()
                .map(this::getCompleteSemanticNetwork)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public Long save(SemanticNetwork semanticNetwork) {
        // 保存语义网络基本信息
        SemanticNetworkDO networkDO = convertToDO(semanticNetwork);
        semanticNetworkMapper.insert(networkDO);
        Long networkId = networkDO.getId();

        // 保存概念对象
        if (semanticNetwork.getConceptObjects() != null) {
            for (ConceptObject conceptObject : semanticNetwork.getConceptObjects()) {
                conceptObject.setSemanticNetworkId(networkId);
                conceptObjectRepository.save(conceptObject);
            }
        }

        // 保存关系项
        if (semanticNetwork.getRelationItemEntity() != null) {
            for (RelationItemEntity relationItem : semanticNetwork.getRelationItemEntity()) {
                relationItem.setSemanticNetworkId(networkId);
                relationItemRepository.save(relationItem);
            }
        }

        // 保存关系定义
        if (semanticNetwork.getRelationDefineEntities() != null) {
            for (RelationDefineEntity relationDefine : semanticNetwork.getRelationDefineEntities()) {
                relationDefine.setSemanticNetworkId(networkId);
                relationDefineRepository.save(relationDefine);
            }
        }

        return networkId;
    }

    @Override
    @Transactional
    public Long save(SemanticNetworkDelta semanticNetworkDelta) {
        // 保存语义网络基本信息
        SemanticNetwork semanticNetwork = semanticNetworkDelta.getSemanticNetwork();
        SemanticNetworkDO networkDO = convertToDO(semanticNetwork);
        networkDO.setName(semanticNetwork.getName());
        Long networkId = networkDO.getId();
        if (semanticNetwork.getId() == null) {
            semanticNetworkMapper.insert(networkDO);
            networkId = networkDO.getId();
        } else {
            semanticNetworkMapper.update(networkDO);
        }
        Long id = networkId;

        DateChange<ConceptObject> conceptObjectChange = semanticNetworkDelta.getConceptObjectChange();

        List<ConceptObject> add = conceptObjectChange.getAdd();
        add.forEach(conceptObject -> {
            conceptObject.setSemanticNetworkId(id);
            conceptObjectRepository.save(conceptObject);
        });

        conceptObjectChange.getDeleteIdList().forEach(conceptObjectId -> {
            conceptObjectRepository.deleteById(conceptObjectId.getId());
        });

        DateChange<RelationDefineEntity> defineEntityChange = semanticNetworkDelta.getRelationDefineEntityDateChange();

        defineEntityChange.getAdd().forEach(relationDefineEntity -> {
            relationDefineEntity.setSemanticNetworkId(id);
            relationDefineRepository.save(relationDefineEntity);
        });

        defineEntityChange.getDeleteIdList().forEach(relationDefineEntity -> {
            relationDefineRepository.deleteById(relationDefineEntity.getId());
            relationDefineItemRepository.deleteByRelationDefineId(relationDefineEntity.getId());
        });

        defineEntityChange.getUpdate().forEach(relationDefineEntity -> {
            relationDefineEntity.setSemanticNetworkId(id);
            relationDefineRepository.update(relationDefineEntity);
        });

        semanticNetworkDelta.getRelationItemEntityChange().getAdd().forEach(relationItemEntity -> {
            relationItemEntity.setSemanticNetworkId(id);
            relationItemRepository.save(relationItemEntity);
        });

        semanticNetworkDelta.getRelationItemEntityChange().getUpdate().forEach(relationItemEntity -> {
            relationItemEntity.setSemanticNetworkId(id);
            relationItemRepository.update(relationItemEntity);
        });

        semanticNetworkDelta.getRelationItemEntityChange().getDeleteIdList().forEach(relationItemEntity -> {
            relationItemRepository.deleteById(relationItemEntity.getId());
        });

        semanticNetworkDelta.getRelationImplEntityDateChange().getAdd().forEach(relationImplEntity -> {
            relationImplEntity.setSemanticNetworkId(id);
            relationImplRepository.save(relationImplEntity);
        });

        semanticNetworkDelta.getRelationImplEntityDateChange().getUpdate().forEach(relationImplEntity -> {
            relationImplRepository.update(relationImplEntity);
        });

        semanticNetworkDelta.getRelationImplEntityDateChange().getDeleteIdList().forEach(relationImplEntity -> {
            relationImplRepository.deleteBySemanticNetworkId(relationImplEntity.getId());
        });

        return networkDO.getId();
    }

    @Override
    @Transactional
    public void update(SemanticNetwork semanticNetwork) {
        // 更新语义网络基本信息
        SemanticNetworkDO networkDO = convertToDO(semanticNetwork);
        semanticNetworkMapper.update(networkDO);
        Long networkId = semanticNetwork.getId();

        // 更新概念对象
        if (semanticNetwork.getConceptObjects() != null) {
            for (ConceptObject conceptObject : semanticNetwork.getConceptObjects()) {
                conceptObject.setSemanticNetworkId(networkId);
                if (conceptObject.getId() == null) {
                    conceptObjectRepository.save(conceptObject);
                } else {
                    conceptObjectRepository.update(conceptObject);
                }
            }
        }

        // 更新关系项
        if (semanticNetwork.getRelationItemEntity() != null) {
            for (RelationItemEntity relationItem : semanticNetwork.getRelationItemEntity()) {
                relationItem.setSemanticNetworkId(networkId);
                if (relationItem.getId() == null) {
                    relationItemRepository.save(relationItem);
                } else {
                    relationItemRepository.update(relationItem);
                }
            }
        }

        // 更新关系定义
        if (semanticNetwork.getRelationDefineEntities() != null) {
            for (RelationDefineEntity relationDefine : semanticNetwork.getRelationDefineEntities()) {
                relationDefine.setSemanticNetworkId(networkId);
                if (relationDefine.getId() == null) {
                    relationDefineRepository.save(relationDefine);
                } else {
                    relationDefineRepository.update(relationDefine);
                }
            }
        }
    }

    @Override
    @Transactional
    public void deleteById(Long id) {
        // 删除关系实现
        relationImplRepository.deleteBySemanticNetworkId(id);

        // 删除关系项
        relationItemRepository.deleteBySemanticNetworkId(id);

        // 删除关系定义
        relationDefineRepository.deleteBySemanticNetworkId(id);

        // 删除概念对象
        conceptObjectRepository.deleteBySemanticNetworkId(id);

        // 删除语义网络
        semanticNetworkMapper.deleteById(id);
    }

    private SemanticNetwork getCompleteSemanticNetwork(SemanticNetworkDO networkDO) {
        SemanticNetwork network = convertToModel(networkDO);

        // 获取概念对象
        List<ConceptObject> conceptObjects = conceptObjectRepository.findBySemanticNetworkId(networkDO.getId());
        network.setConceptObjects(conceptObjects);

        // 获取关系项
        List<RelationItemEntity> relationItems = relationItemRepository.findBySemanticNetworkId(networkDO.getId());
        network.setRelationItemEntity(relationItems);

        Map<Long, RelationItemEntity> itemIdEntityMap = new HashMap<>();

        Map<RelationItem, RelationImplEntity> itemEntityMap = new HashMap<>();

        relationItems.forEach(relationItemEntity -> {
            itemIdEntityMap.put(relationItemEntity.getId(), relationItemEntity);
        });

        // 获取关系定义
        List<RelationDefineEntity> relationDefines = relationDefineRepository.findBySemanticNetworkId(networkDO.getId());
        network.setRelationDefineEntities(relationDefines);

        List<RelationImplEntity> semanticNetworkId = relationImplRepository.findBySemanticNetworkId(networkDO.getId());

        semanticNetworkId.forEach(relationImplEntity -> {
            RelationItemEntity relationItemEntity = itemIdEntityMap.get(relationImplEntity.getRelationItemId());
            RelationItem relationItem = relationItemEntity.toRelationItem();
            itemEntityMap.put(relationItem, relationImplEntity);
        });
        network.setItemImplEntityMap(itemEntityMap);
        return network;
    }

    private SemanticNetwork convertToModel(SemanticNetworkDO networkDO) {
        if (networkDO == null) {
            return null;
        }
        SemanticNetwork network = new SemanticNetwork();
        network.setId(networkDO.getId());
        network.setName(networkDO.getName());
        network.setUserId(networkDO.getUserId());
        return network;
    }

    private SemanticNetworkDO convertToDO(SemanticNetwork network) {
        if (network == null) {
            return null;
        }
        SemanticNetworkDO networkDO = new SemanticNetworkDO();
        networkDO.setId(network.getId());
        networkDO.setName(network.getName());
        networkDO.setUserId(network.getUserId());
        return networkDO;
    }

    private SemanticNetworkDO convertToDO(SemanticNetworkDelta networkDelta) {
        if (networkDelta == null) {
            return null;
        }
        SemanticNetworkDO networkDO = new SemanticNetworkDO();
        networkDO.setId(networkDelta.getId());
        networkDO.setName(networkDelta.getName());
        networkDO.setUserId(networkDelta.getUserId());
        return networkDO;
    }
} 